package com.wormhole.wormholemanagement.utils;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class SpecificationBuilder {

    // 类型转换器映射
    private static final Map<Class<?>, Function<String, ?>> CONVERTERS = Map.of(
            Boolean.class, "true"::equalsIgnoreCase,
            Integer.class, Integer::valueOf,
            Long.class, Long::valueOf,
            String.class, s -> s
            // 添加其他需要的类型转换...
    );

    public static <T> Specification<T> buildSpecification(Map<String, String> params) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            params.forEach((key, value) -> {
                if (shouldIgnoreParam(key)) return;
                // 特殊处理: fileSize参数实现小于等于查询

                try {

                    boolean isFuzzyMatch = key.startsWith("like_");
                    String fieldName = isFuzzyMatch ? key.substring(5) : key;

                    Path<?> path = root.get(fieldName);
                    Class<?> fieldType = path.getJavaType();

                    // 特殊处理: isMovedToArchive字段
                    if ("isMovedToArchive".equals(key)) {
                        handleIsMovedToArchive(root, cb, predicates, value);
                        return;
                    }

                    if ("fileSize".equals(key)) {
                        Long fileSizeValue = Long.valueOf(value);
                        predicates.add(cb.lessThanOrEqualTo(root.get("fileSize"), fileSizeValue));
                        return;
                    }
                    // 通用布尔字段处理（适用于任何布尔类型字段）
                    if (fieldType == Boolean.class || fieldType == boolean.class) {
                        Boolean boolValue = "true".equalsIgnoreCase(value);
                        predicates.add(cb.equal(root.get(fieldName), boolValue));
                        return; // 布尔字段处理完成后直接返回
                    }

                    // 模糊匹配的字符串字段
                    if (isFuzzyMatch && fieldType == String.class) {
                        predicates.add(cb.like(
                                cb.lower(root.get(fieldName)),
                                "%" + value.toLowerCase() + "%"
                        ));
                    }
                    // 精确匹配的其他字段
                    else {
                        Function<String, ?> converter = CONVERTERS.getOrDefault(
                                fieldType,
                                s -> s
                        );
                        Object convertedValue = converter.apply(value);
                        predicates.add(cb.equal(root.get(fieldName), convertedValue));
                    }


                } catch (IllegalArgumentException e) {
                    System.err.println("Unknown field: " + key);
                } catch (Exception e) {
                    System.err.println("Convert failed for field: " + key + ", value: " + value);
                }
            });

            return cb.and(predicates.toArray(new Predicate[0]));
        };
    }

    private static boolean shouldIgnoreParam(String key) {
        return key == null ||
                "page".equals(key) ||
                "size".equals(key) ||
                "sort".equals(key);
    }
    // 新增处理 isMovedToArchive 字段的方法
    private static <T> void handleIsMovedToArchive(Root<T> root, CriteriaBuilder cb,
                                                   List<Predicate> predicates, String value) {
        switch (value) {
            case "1":
                // 1的时候isMovedToArchive这个字段的值为true
                predicates.add(cb.equal(root.get("isMovedToArchive"), true));
                break;
            case "2":
                // 2的时候isMovedToArchive为false
                predicates.add(cb.equal(root.get("isMovedToArchive"), false));
                break;
            case "3":
                // 3的时候isMovedToArchive等于空或者null
                predicates.add(cb.isNull(root.get("isMovedToArchive")));
                break;
            default:
                // 其他情况可以忽略或者按需处理
                break;
        }
    }
}